package org.changs.monitor;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.databinding.DataBindingUtil;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;

import org.changs.aplug.base.BaseFragment;
import org.changs.monitor.camera.CameraUtils;
import org.changs.monitor.databinding.TestCameraBinding;
import org.changs.monitor.view.AutoFitTextureView;

import java.util.ArrayList;
import java.util.List;

import timber.log.Timber;

/**
 * Created by yincs on 2017/11/7.
 */

public class TestFragment extends BaseFragment {
    private TestCameraBinding mBinding;
    private CameraDevice mCameraDevice;
    private CameraCharacteristics mCameraCharacteristics;
    private android.util.Size mVideoSize;
    private Surface mSurface;

    private ImageReader mImageReader;

    @Override
    public View setup(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.test_camera, container, false);
        return mBinding.getRoot();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        mBinding.texture.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                openCamera();
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {

            }
        });
    }

    @SuppressLint("MissingPermission")
    private void openCamera() {
        CameraManager cameraManager =
                (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
        try {
            mCameraCharacteristics = cameraManager.getCameraCharacteristics("0");
            StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            mVideoSize = CameraUtils.chooseVideoSize(map.getOutputSizes(MediaRecorder.class));

            cameraManager.openCamera("0", new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    mCameraDevice = camera;
                    updateSession();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    mCameraDevice = camera;
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    mCameraDevice = camera;
                }
            }, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void updateSession() {
        try {
            List<Surface> outputs = new ArrayList<>();
            outputs.add(new Surface(mBinding.texture.getSurfaceTexture()));
            outputs.add(getImageReaderSurface());
            mCameraDevice.createCaptureSession(outputs, new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    try {
                        AutoFitTextureView textureView = mBinding.texture;
                        StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                        Size previewSize = CameraUtils.chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                                textureView.getWidth(), textureView.getHeight(), mVideoSize);
                        int orientation = getResources().getConfiguration().orientation;
                        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                            textureView.setAspectRatio(previewSize.getWidth(), previewSize.getHeight());
                        } else {
                            textureView.setAspectRatio(previewSize.getHeight(), previewSize.getWidth());
                        }
                        textureView.getSurfaceTexture().setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
                        CameraUtils.configureTransform(textureView, previewSize);
                        mSurface = new Surface(textureView.getSurfaceTexture());

                        CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                        builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
                        builder.addTarget(mSurface);
                        builder.addTarget(getImageReaderSurface());
                        session.setRepeatingRequest(builder.build(), null, null);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Surface getImageReaderSurface() {
        if (mImageReader == null) {
            mImageReader = ImageReader.newInstance(mVideoSize.getWidth(), mVideoSize.getHeight(), ImageFormat.JPEG, 1);
            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    Timber.d("onImageAvailable() called with: reader = [" + reader + "]");
                    Image image = reader.acquireNextImage();
                    reader.close();
//                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
//                    byte[] bytes = new byte[buffer.remaining()];
//                    buffer.get(bytes);
//                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                }
            }, null);
        }
        return mImageReader.getSurface();
    }


}
